package com.httpClient.chapter1;

import com.sky.JULLog.MyJulLogger;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.message.BasicNameValuePair;
import org.junit.Test;


import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

/**
 * @author : wushikai
 * <p>
 * date : 2024-06-17
 */
public class Chapter1 {


    private static Logger log = MyJulLogger.getLogger(Chapter1.class);


    static {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");   //这样会输出代理class文件
    }


    @Test
    public void simpleUse() throws IOException, URISyntaxException {

        HttpClient httpclient = HttpClients.createDefault();   //new 一个httpClient

        URI uri = URIUtils.createURI(
                "http",
                "localhost",
                8000,
                "/xy/expose/merDetail",
                "sp.lk.merchant_name=广西",       //mark 自己手写可能出错, 使用 namePair 对象, 一般不会错
                null
        );                         //也可以构造 一个uri, 这个uri 被URL 使用并解析, 最后连接
        HttpGet httpget = new HttpGet(uri);
        HttpResponse response = httpclient.execute(httpget);  //使用 httpClient 调用 get请求
        handleResponse(response);

    }

    @Test
    public void userNamePair() throws URISyntaxException, IOException {

        HttpClient httpclient = HttpClients.createDefault();   //new 一个httpClient

        //   HttpGet httpget = new HttpGet("http://localhost:8000/xy/expose/merDetail");   //new 一个 get请求, mark 你自己创一个

        List<NameValuePair> nameValuePairList = new ArrayList<>();
        nameValuePairList.add(new BasicNameValuePair("sp.lk.merchant_name", "广西"));

        URI uri = URIUtils.createURI(
                "http",
                "localhost",
                8000,
                "/xy/expose/merDetail",
                URLEncodedUtils.format(nameValuePairList, "UTF-8"),
                null
        );
        HttpGet httpget = new HttpGet(uri);
        System.out.println(httpget.getURI());

        HttpResponse response = httpclient.execute(httpget);  //使用 httpClient 调用 get请求
//        handleResponse(response);
        handleResponseRepeatedly(response);
    }


    /**
     * 使用最简单的 流式读取
     */
    private static void handleResponse(HttpResponse response) throws IOException {

        System.out.println("response 的实现类是==>" + response.getClass().getCanonicalName());
        log.info("协议版本:" + response.getProtocolVersion());
        log.info("服务器返回状态码:" + response.getStatusLine().getStatusCode());
        log.info("服务器返回状态码表述:" + response.getStatusLine().getReasonPhrase());
        log.info("服务器返回状态描述:" + response.getStatusLine().toString());

        //使用 响应头 获取 cookie 键值对,  注意这是没有被解析过的
        Header h1 = response.getFirstHeader("Set-Cookie");
        log.info(h1.toString());
        Header h2 = response.getLastHeader("Set-Cookie");
        log.info(h2.toString());
        Header[] hs = response.getHeaders("Set-Cookie");
        log.info(hs.length + "");

        //使用 迭代器 获取 cookie 键值对 ,  httpClient 帮你解析好;
        HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator("Set-Cookie"));
        while (it.hasNext()) {
            HeaderElement elem = it.nextElement();
            log.info(elem.getName() + " = " + elem.getValue());
            NameValuePair[] params = elem.getParameters();
            for (NameValuePair param : params) {
                log.info(" " + param);
            }
        }


        HttpEntity entity = response.getEntity();   // 返回一个 HttpResponse 的 entity(实体) 这个  实体 = 响应头+响应内容

        if (entity != null) {
            InputStream inputStream = entity.getContent();   //实体对象 获取流 , 解析data 即可;
            byte[] buffer = new byte[2048];
            while (inputStream.read(buffer) != -1) {
                log.info("第一次读取的内容是:" + new String(buffer, StandardCharsets.UTF_8));
            }
            System.out.println();
            System.out.println("data  read  finished.......");
            try {
                buffer = new byte[2048];
                InputStream inputStreamAgain = entity.getContent();   //第二次读取
                int read = inputStreamAgain.read(buffer);//已经读完了, 还能继续 读吗?
                log.warning("第二次读取的字节数是" + read + " ,  读取的内容是  " + new String(buffer, StandardCharsets.UTF_8));
            } catch (Exception e) {
                log.severe(e.getMessage());
            }
        }
    }


    /**
     * 使用 缓冲流, 复制一份内容到内存缓冲区, 实现多次读取
     */
    private static void handleResponseRepeatedly(HttpResponse response) throws IOException {


        HttpEntity entity = response.getEntity();   // 返回一个 HttpResponse 的 entity(实体) 这个  实体 = 响应头+响应内容

        byte[] buffer = new byte[2048];
        if (entity != null) {
            BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(entity);
            InputStream inputStream = bufferedHttpEntity.getContent();
            while (inputStream.read(buffer) != -1) {
                log.info("第一次读取的内容是:\n" + new String(buffer, StandardCharsets.UTF_8));
            }

            System.out.println("data  read  finished.......");


            buffer = new byte[2048];
            //mark 这个bufferedHttpEntity  第二次获取流中的内容, 只不过这个流不在socket 中了, 而是内存
            InputStream inputStreamAgain = bufferedHttpEntity.getContent();
            int read = inputStreamAgain.read(buffer);
            log.warning("第二次读取的字节数是" + read + " ,  读取的内容是  " + new String(buffer, StandardCharsets.UTF_8));


        }


    }


}
